home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 7
/
Apprentice-Release7.iso
/
Source Code
/
Pascal
/
Code Resources
/
Ingis WDEF 1.3
/
IngisWDEF.p
< prev
next >
Wrap
Text File
|
1997-05-09
|
19KB
|
550 lines
{ *** Main unit for the "IngisWDEF" WDEF building package *** }
{© 1994-1997 by Ingemar Ragnemalm}
{You may use it freely as long as credits are given in the final program.}
{*** IngisWDEF ***}
{}
{Version 1.3}
{}
{This WDEF is written in order to be as easily customized as possible, in order to produce new}
{interesting WDEFs. The code consists of two parts, IngisWDEF.p and CustomStubs.p. The idea is}
{to separate code that must be changed from code that can remain the same.}
{}
{The code in IngisWDEF will seldom have to be modified when making a new WDEF.}
{}
{CustomStub (which comes in several versions, one for each demo and one with empty stubs)}
{is where your code goes. You create a grow region, a close box, draw the drag bar and create the}
{contents and drag regions.}
{}
{An important point with IngisWDEF is that it uses regions rather than rectangles wherever possible.}
{This makes it very easy to modify it for making windows with non-rectangular shapes. Few other}
{WDEF samples do that - surprisingly few! Also, I have seen only a single WDEF that allowed}
{resizing with color windows, and that was rectangular.}
{}
{BTW, I found the best way to develop a WDEF with Think Pascal: use a working application (small -}
{Skel is perfect) as its resource file! The application should be configured to use our WDEF for one}
{window. That way, "build code resource" makes a copy of that application with our WDEF in it.}
{Build, switch to Finder and run. Simple! Who needs a special "WDEF tester"? (OK, perhaps for}
{changing the variant code.)}
{}
{Close box is assumed to be rectangular - could perhaps be generalized. Lots and lots of out of}
{memory checks! (All those regions that can take our last byte!) Better rules for deciding color/BW.}
{Standard colors from the appropriate resource instead of the standard blue tint. Better routine}
{and variable names.}
{}
{ASSUMPTIONS that are not necessarily right:}
{- Close/zoom boxes always rectangular and only one of each.}
{- All the window is contents, drag area, frame or shadow - no "dead" parts.}
{Version 1.1:}
{Adds support for CodeWarrior.}
{Version 1.2:}
{Updated for CW9.}
{Version 1.3:}
{Fixes a serious bug that could lead to problems when hiding the application.}
{Adds support for user defined globals.}
{On the wish list, perhaps for a future release:}
{- Separate handling of parts in different screens}
{- Fat binary}
unit IngisWDEF;
interface
uses
{$IFC UNDEFINED THINK_PASCAL}
Types, QuickDraw, ToolUtils, Windows, Events, Memory, OSUtils,
{$ENDC}
CustomStubs, IngisWDEFUtils;
{$MAIN}
function main (varCode: integer; macWindow: WindowPeek; theMessage: integer; param: longint): longint;
implementation
type
RectPtr = ^Rect; {For passing the parameter to DrawGrow}
{******************************************************}
{ GetDragBar }
{ }
{ Pass back a region which encloses the drag bar of the window }
{ Note: dragRgn must already be initialized! }
{ You can probably leave this routine without change! }
{ We assume that the contRgn minus the strucRgn, frame and shadow is the dragRgn!}
{ *****************************************************}
procedure GetDragBar (varCode: integer; macWindow: WindowPeek; var dragRgn: RgnHandle);
var
radius: integer;
dragBar: Rect;
begin
CopyRgn(macWindow^.strucRgn, dragRgn);
OffsetRgn(dragRgn, -kShadowLength, -kShadowLength);
SectRgn(dragRgn, macWindow^.strucRgn, dragRgn);
DiffRgn(dragRgn, macWindow^.contRgn, dragRgn);
InsetRgn(dragRgn, kFrameWidth, kFrameWidth);
end;
{*****************************************************************************}
{ DrawFrame}
{}
{ Draw the entire window frame. Calls several custom routines!}
{ *****************************************************************************}
procedure DrawFrame (varCode: integer; macWindow: WindowPeek);
var
wFrame: Rect; { Window frame around content rgn }
wFrameRgn: RgnHandle;
tmpPt: Point;
dragBar: RgnHandle; { Drag bar of window }
savePen: PenState; { Current pen characteristics }
saveForeColor, saveBackColor: RGBColor;
colorFlag: Boolean;
closeBox, zoomBox: Rect;
begin
SaveColors(saveForeColor, saveBackColor);
GetPenState(savePen); { Save the current pen state }
{ Structure region of a window has four parts: }
{ (1) Frame around the content region }
{ (2) Drop shadow }
{ (3) Drag bar }
{ (4) Close box inside the drag bar }
{ (1) Frame around content region }
wFrameRgn := NewRgn;
CopyRgn(macWindow^.contRgn, wFrameRgn);
InsetRgn(wFrameRgn, -kFrameWidth, -kFrameWidth);
PenSize(kFrameWidth, kFrameWidth);
FrameRgn(wFrameRgn);
{DisposeRgn(wFrameRgn); Not yet- we'll reuse it}
{ (2) Drop shadow below and to the right of content region }
PenSize(kShadowLength, kShadowLength);
CopyRgn(macWindow^.strucRgn, wFrameRgn);
OffsetRgn(wFrameRgn, -kShadowLength, -kShadowLength);
DiffRgn(macWindow^.strucRgn, wFrameRgn, wFrameRgn);
ForeColor(blackColor);
PaintRgn(wFrameRgn);
DisposeRgn(wFrameRgn);
dragBar := NewRgn;
GetDragBar(varCode, macWindow, dragBar);
colorFlag := BitAnd(macWindow^.port.portBits.rowBytes, $8000) <> 0;
if colorFlag then
colorFlag := CGrafPtr(macWindow)^.portPixMap^^.pixelSize >= kMinDepthForColor;
DrawDragBar(varCode, macWindow, dragBar, colorFlag);
DefaultColors;
if macWindow^.hilited then
if macWindow^.goAwayFlag then
begin { Make sure window has a close box }
GetCloseBox(varCode, dragBar, closeBox);
DrawCloseBox(varCode, macWindow, closeBox, colorFlag);
end;
if macWindow^.hilited then
if macWindow^.spareFlag then
begin { Make sure window has a zoom box }
GetZoomBox(varCode, dragBar, zoomBox);
DrawZoomBox(varCode, macWindow, zoomBox, colorFlag);
end;
InsetRgn(dragBar, -kFrameWidth, -kFrameWidth);
PenSize(kFrameWidth, kFrameWidth);
DefaultColors;
FrameRgn(dragBar);
DisposeRgn(dragBar);
SetPenState(savePen); { Restore original pen state }
RestoreColors(saveForeColor, saveBackColor);
end;
{*****************************************************************************}
{ DoToggleCloseBox}
{}
{ Toggle hiliting of the close box.}
{ *****************************************************************************}
procedure DoToggleCloseBox (varCode: integer; macWindow: WindowPeek);
var
dragBar: RgnHandle; { Rectangle enclosing drag bar }
closeBox: Rect; { Rectangle enclosing close box }
colorFlag: Boolean;
saveForeColor, saveBackColor: RGBColor;
pt: Point;
begin
dragBar := NewRgn;
GetDragBar(varCode, macWindow, dragBar);
SetRect(closeBox, 0, 0, 0, 0); {If GetCloseBox does nothing, we want an empty rect.}
if macWindow^.goAwayFlag then
begin
GetCloseBox(varCode, dragBar, closeBox);
colorFlag := BitAnd(macWindow^.port.portBits.rowBytes, $8000) <> 0;
if colorFlag then
colorFlag := CGrafPtr(macWindow)^.portPixMap^^.pixelSize >= kMinDepthForColor;
GetMouse(pt); {Get a point for PtInRect}
if colorFlag then
SaveColors(saveForeColor, saveBackColor);
if PtInRect(pt, closeBox) and Button then
DrawHitCloseBox(varCode, macWindow, closeBox, colorFlag)
else
DrawCloseBox(varCode, macWindow, closeBox, colorFlag);
if colorFlag then
RestoreColors(saveForeColor, saveBackColor);
end;
DisposeRgn(dragBar);
end; {DoToggleCloseBox}
{ Same as above, but for the zoom box! }
procedure DoToggleZoomBox (varCode: integer; macWindow: WindowPeek);
var
dragBar: RgnHandle; { Rectangle enclosing drag bar }
zoomBox: Rect; { Rectangle enclosing close box }
colorFlag: Boolean;
saveForeColor, saveBackColor: RGBColor;
pt: Point;
begin
dragBar := NewRgn;
GetDragBar(varCode, macWindow, dragBar);
SetRect(zoomBox, 0, 0, 0, 0); {If GetZoomBox does nothing, we want an empty rect.}
if macWindow^.spareFlag then
begin
GetZoomBox(varCode, dragBar, zoomBox);
colorFlag := BitAnd(macWindow^.port.portBits.rowBytes, $8000) <> 0;
if colorFlag then
colorFlag := CGrafPtr(macWindow)^.portPixMap^^.pixelSize >= kMinDepthForColor;
GetMouse(pt); {Get a point for PtInRect}
if colorFlag then
SaveColors(saveForeColor, saveBackColor);
if PtInRect(pt, zoomBox) and Button then
DrawHitZoomBox(varCode, macWindow, zoomBox, colorFlag)
else
DrawZoomBox(varCode, macWindow, zoomBox, colorFlag);
if colorFlag then
RestoreColors(saveForeColor, saveBackColor);
end;
DisposeRgn(dragBar);
end; {DoToggleZoomBox}
{A little padding around LocalToGlobal.}
procedure MyLocalToGlobal (macWindow: univ WindowPtr; var p: Point);
var
savePort: GrafPtr;
begin
GetPort(savePort);
SetPort(macWindow);
LocalToGlobal(p);
SetPort(savePort);
end;
{*****************************************************************************}
{ FindPart}
{}
{ Find which part of the window was hit by a mouse click at the}
{ specified location.}
{ *****************************************************************************}
function FindPart (varCode: integer; macWindow: WindowPeek; location: longint): integer;
var
theClick: Point; { Global coords of mouse click }
dragBar, growRgn: RgnHandle;
closeBox, zoomBox, portR: Rect;
begin
theClick.h := LoWord(location); { Extract horizontal component }
theClick.v := HiWord(location); { Extract vertical component }
{ Are we inside the window structure at all?}
if not PtInRgn(theClick, macWindow^.strucRgn) then
begin
FindPart := wNoHit;
Exit(FindPart);
end;
{Must check grow before contRgn, since grow is (often) a part of the contRgn.}
growRgn := NewRgn;
GetGrowRgn(varCode, macWindow, growRgn);
if PtInRgn(theClick, growRgn) then
begin
FindPart := wInGrow;
DisposeRgn(growRgn);
exit(FindPart);
end;
DisposeRgn(growRgn);
if PtInRgn(theClick, macWindow^.contRgn) then
begin
FindPart := wInContent; { Content region }
Exit(FindPart);
end;
dragBar := NewRgn;
{ Drag bar? }
GetDragBar(varCode, macWindow, dragBar);
if PtInRgn(theClick, dragBar) then
begin { Drag bar or close box! }
SetRect(closeBox, 0, 0, 0, 0); {If GetCloseBox does nothing, we want an empty rect.}
if macWindow^.goAwayFlag then
GetCloseBox(varCode, dragBar, closeBox);
SetRect(zoomBox, 0, 0, 0, 0); {If GetZoomBox does nothing, we want an empty rect.}
if macWindow^.spareFlag then
GetZoomBox(varCode, dragBar, zoomBox);
if macWindow^.goAwayFlag and PtInRect(theClick, closeBox) then
FindPart := wInGoAway { Close box! }
else if macWindow^.spareFlag and PtInRect(theClick, zoomBox) then
begin
{Compare the size of portRect with stdState!}
portR := macWindow^.port.portRect;
with WStateDataHandle(macWindow^.dataHandle)^^ do
if ((portR.right - portR.left) = (stdState.right - stdState.left)) and ((portR.bottom - portR.top) = (stdState.bottom - stdState.top)) then
begin
FindPart := wInZoomIn;
end
else
begin {Not match - save the portRect as the userState}
FindPart := wInZoomOut;
MyLocalToGlobal(macWindow, portR.topLeft);
MyLocalToGlobal(macWindow, portR.botRight);
WStateDataHandle(macWindow^.dataHandle)^^.userState := portR;
end;
end
else
FindPart := wInDrag; { Drag bar and NOT close box! }
end
else
FindPart := wNoHit; { Click somewhere else. Don't bother. }
DisposeRgn(dragBar);
end;
{*****************************************************************************}
{ BuildRegions}
{}
{ Build the structure and content region of a window.}
{ *****************************************************************************}
procedure BuildRegions (varCode: integer; macWindow: WindowPeek);
var
theRect: Rect; { Window regions are rectangular }
theRgn: RgnHandle; { Region defining drop shadow - and everything else we need a temprary region for }
begin
{The content region should be calculated from the port rectangle - but, of course, does not}
{have to be identical to it.}
{Init the region.}
theRgn := NewRgn; { Define region for the shadow }
theRect := macWindow^.port.portRect;
MyLocalToGlobal(macWindow, theRect.topLeft);
MyLocalToGlobal(macWindow, theRect.botRight);
{CUSTOM: Given the varCode and rectangle, create contRgn and dragRgn (returned in strucRgn)!}
BuildCustomRegions(varCode, theRect, macWindow^.contRgn, macWindow^.strucRgn);
{Build struc, add frame and shadow:}
{struc := cont + drag}
UnionRgn(macWindow^.contRgn, macWindow^.strucRgn, macWindow^.strucRgn);
{Expand struc to include frame}
InsetRgn(macWindow^.strucRgn, -kFrameWidth, -kFrameWidth);
{Make a copy}
CopyRgn(macWindow^.strucRgn, theRgn);
{Offset it for the shadow}
OffsetRgn(theRgn, kShadowLength, kShadowLength);
{struc := struc + shadow}
UnionRgn(macWindow^.strucRgn, theRgn, macWindow^.strucRgn);
DisposeRgn(theRgn); { All thru with region }
end; {BuildRegions}
{*****************************************************************************}
{ DrawGrowFrame - Drawing the frame during window resizing. }
{ *****************************************************************************}
procedure DrawGrowFrame (varCode: integer; macWindow: WindowPeek; theRect: Rect);
var
tmpContRgn, tmpDragRgn: RgnHandle;
saveForeColor, saveBackColor: RGBColor;
begin
SaveColors(saveForeColor, saveBackColor);
with theRect do
begin
if right - left < kMinWidth then
right := left + kMinWidth;
if bottom - top < kMinHeight then
bottom := top + kMinHeight;
end;
tmpContRgn := NewRgn;
tmpDragRgn := NewRgn;
BuildCustomRegions(varCode, theRect, tmpContRgn, tmpDragRgn);
InsetRgn(tmpContRgn, -kFrameWidth, -kFrameWidth);
InsetRgn(tmpDragRgn, -kFrameWidth, -kFrameWidth);
FrameRgn(tmpContRgn);
FrameRgn(tmpDragRgn);
DisposeRgn(tmpContRgn);
DisposeRgn(tmpDragRgn);
{The above is well enough, but we also provide a stub for some extra:}
DrawScrollFrame(varCode, macWindow, theRect);
RestoreColors(saveForeColor, saveBackColor);
end;
{*****************************************************************************}
{ PrepareGrowIcon - Sets up for the custom routine that draws the grow icon. }
{*****************************************************************************}
procedure PrepareGrowIcon (varCode: integer; macWindow: WindowPeek; theRect: Rect);
var
tmpRect, smallRect, largeRect: Rect;
var
tempClip, saveClip, growRgn: RgnHandle;
savePort: GrafPtr;
saveForeColor, saveBackColor: RGBColor;
colorFlag: Boolean;
begin
SaveColors(saveForeColor, saveBackColor);
theRect := macWindow^.port.portRect;
MyLocalToGlobal(macWindow, theRect.topLeft);
MyLocalToGlobal(macWindow, theRect.botRight);
tempClip := NewRgn;
saveClip := NewRgn;
growRgn := NewRgn;
GetGrowRgn(varCode, macWindow, growRgn);
SectRgn(macWindow^.port.visRgn, macWindow^.port.clipRgn, tempClip);
GetClip(saveClip);
OffsetRgn(tempClip, -macWindow^.port.portRect.left + theRect.left, -macWindow^.port.portRect.top + theRect.top);
SetClip(tempClip);
DrawScrollFrame(varCode, macWindow, theRect); {Standard eller fritt val?}
DefaultColors;
colorFlag := BitAnd(macWindow^.port.portBits.rowBytes, $8000) <> 0;
if colorFlag then
colorFlag := CGrafPtr(macWindow)^.portPixMap^^.pixelSize >= kMinDepthForColor;
DrawTheGrowIcon(varCode, WindowPeek(macWindow), theRect, growRgn, colorFlag);
RestoreColors(saveForeColor, saveBackColor);
SetClip(saveClip);
DisposeRgn(saveClip);
DisposeRgn(tempClip);
DisposeRgn(growRgn);
end;
{*****************************************************************************}
{ SyncPorts - the ugly patch for making it work with Color QD. ONLY called when CQD i available! }
{ *****************************************************************************}
procedure SyncPorts;
var
bwPort: GrafPtr;
colorPort: CGrafPtr;
begin
GetWMgrPort(bwPort);
GetCWMgrPort(colorPort);
SetPort(GrafPtr(colorPort));
{Copy some fields:}
BlockMove(@bwPort^.pnLoc, @colorPort^.pnLoc, 10);
BlockMove(@bwPort^.pnVis, @colorPort^.pnVis, 14);
PenPat(bwPort^.pnPat);
BackPat(bwPort^.bkPat);
end;
{*****************************************************************************}
{ Main Function}
{ *****************************************************************************}
{$MAIN}
function main (varCode: integer; macWindow: WindowPeek; theMessage: integer; param: longint): longint;
var
needSyncPorts: Boolean;
savePort: GrafPtr;
theRect: Rect;
begin
main := 0;
GetPort(savePort);
{Must sync ports on all QuickDraw-dependent routines!}
if HasCQDraw then {and (theMessage in [wDraw, wHit, wGrow, wDrawGIcon, wCalcRgns])}
SyncPorts;
case theMessage of { Take appropriate action }
wNew:
begin
if macWindow^.dataHandle = nil then
macWindow^.dataHandle := NewHandleClear(Sizeof(MyDataRecord)); {Allocate space for WStateData AND custom globals!}
with WStateDataHandle(macWindow^.dataHandle)^^ do
begin
stdState := macWindow^.port.portRect;
MyLocalToGlobal(macWindow, stdState.topLeft);
MyLocalToGlobal(macWindow, stdState.botRight);
userState := stdState;
end;
InitMyWindow(varCode, WindowPeek(macWindow));
end;
wDispose:
begin
DisposeMyWindow(varCode, macWindow);
if macWindow^.dataHandle <> nil then
DisposeHandle(macWindow^.dataHandle);
macWindow^.dataHandle := nil;
end;
wDraw: { Draw the window frame }
if macWindow^.visible then { Only draw if window is visible }
case BAnd(param, $0000FFFF) of { Find out which part to draw }
wNoHit: { Draw the entire frame }
begin
DrawFrame(varCode, macWindow);
end;
wInGoAway: { Toggle hiliting of the close box }
DoToggleCloseBox(varCode, macWindow);
wInZoomIn, wInZoomOut: { Toggle hiliting of the close box }
DoToggleZoomBox(varCode, macWindow);
end;
wHit: { Find part of window clicked in }
main := FindPart(varCode, macWindow, param);
wCalcRgns: { Build structure & content rgns }
BuildRegions(varCode, macWindow);
wGrow:
DrawGrowFrame(varCode, macWindow, RectPtr(param)^);
wDrawGIcon:
PrepareGrowIcon(varCode, macWindow, theRect); {Set up and calls DrawTheGrowIcon}
end; {case}
SetPort(savePort);
end; {main}
end.